home *** CD-ROM | disk | FTP | other *** search
/ Amiga Mag HDD Backup / Amiga Mag HDD Backup.zip / Amiga Mag HDD Backup / Alexander.img.bin / Alexander.img / 315 2 files Archive.sit / Any plain-text files / ? Any plain-text file 73 < prev    next >
Text File  |  1995-01-03  |  19KB  |  163 lines

  1. eq *req,
  2.                    struct GenericDevice *dev )
  3. {
  4.    /*
  5.     *  perform any per task device cleanup before
  6.     *  the calling task releases the device
  7.    */
  8.  
  9.    return;
  10. }
  11.  
  12. /*=======================================================*/
  13. /*
  14.  *  usr_devExpunge() - remove a device
  15.  *
  16.  *  The memory allocator calls this procedure when system
  17.  *  is low on memory.  Since it is called by the memory
  18.  *  allocator, it MUST return as quickly as possible.
  19.  *
  20.  *  It is also called when the open count for the
  21.  *  device reaches 0.
  22.  *
  23.  *  If this procedure returns 0, the device will not be
  24.  *  removed from the system.  
  25.  *  If it returns a non-zero value, the device will be
  26.  *  removed and the memory allocated for it will be
  27.  *  freed.
  28.  *
  29. */
  30. /*=======================================================*/
  31.  
  32. int usr_devExpunge( struct GenericDevice *dev )
  33. {
  34.  
  35.    /*
  36.     *  No one is using the device.
  37.     *
  38.     *  Return 1 to allow the device to be removed and
  39.     *  its memory freed.  First, free any memory you
  40.     *  allocated Using ARexx Time and Date Functions
  41. by Merrill Callaway
  42.  
  43. When I was a child, my Grandmother used to fascinate me with a computational trick: She knew how to figure in her head in just a few seconds what day of the week any given day-month-year date would fall.  I never did figure out her method, but thanks to ARexx, we need never worry about computing time, days and dates.  ARexx has a full set of functions to make it easy to figure out all sorts of problems involving day of the week, time or dates.  This month's programs are two that I made after a couple of embarrassing or expensive calls to my mates Down Under in Australia.  Because of the time and day differences, I found that I either woke a friend late at night or rang a business outside office hours.  
  44. What Time is It?
  45. World timekeeping is based upon the offset behind or ahead of Greenwich Mean Time, (GMT) the time at 0 degrees longitude in Greenwich, England.  The Pacific coast of the USA, for example, is eight hours behind GMT and the Atlantic coast is only five hours behind GMT.  I live in the Mountain Time Zone and my offset is 7 hours.  You can find any time in the world with your Amiga, if your System includes Locale.  Open Prefs in your System Directory and click on Locale to get a World map showing time offsets from GMT.  Click anywhere to see the local time's offset from GMT.  Try clicking on Newfoundland, Canada or on central Australia.  These times are offset by 30 minutes, not whole hours.  Can you find others?  You may think, "All I have to do is add up the offsets of here and there (Australia for instance), to get the time difference."  While the problem is not too difficult, it is not quite as easy as that.  What about Daylight Savings Time?  What about Daylight Time in Australia?  Aren't their seasons reversed from ours?  Does your long distance carrier have discount rates to foreign countries?  They usually put in a few discount hours that coincide with a few business hours where you are calling.  Our programs will address these questions.  If you don't have a mate in Sydney, Australia, or don't live in my time zone, the program is easily adapted for anywhere else in the world.  As an exercise, you may want to dress up the program so that there is opportunity for the user to input any locale (such as large cities around the world) and let the program take care of everything else.
  46.  
  47. The Computations
  48. Prefs/Locale shows that MST is offset 7 hours from GMT.  Sydney, Australia is 10 hours ahead of GMT.  In summer, Mountain Daylight Time puts the clock ahead one hour, reducing the local time offset to 6 hours behind GMT.  For Daylight Savings Time move your locale offset number one hour to the right (east) and going back to regular time use the given number (Spring Ahead, Fall Back).  Moving to the right will decrease your offset if you are west of GMT and increase it if you are east of GMT.  The International Date Line divides "east" from "west" (see below).  Thus MST is 7 hours and MDT is 6 hours behind GMT.  Sydney's standard (winter) time is GMT plus 10.  Since they are having WINTER when we are having summer (and daylight time), the proper calculation for Sydney is 16 hours ahead of MDT (Daylight time).  In winter, MST is 7 hours behind GMT, but Sydney has moved into SUMMER down under and their offset moves to the right one hour (11 hours ahead of GMT).  So in my winter, I must add 18 hours to my time to get the local time in Sydney.  For destinations in the Northern Hemisphere, of course you do not need to change offsets as they will be in step year round.
  49.  
  50. What Day Is It?
  51. In the Pacific Ocean east of New Zealand is the International Date Line, a line along 180 degrees longitude, except where it veers so as not to bisect countries.  Just to the west of the line, time is deemed to be 12 hours ahead of GMT and just to the east of the line time is 12 hours behind GMT.  In other words, the date changes abruptly from Monday east of the line to Tuesday west of it.  (Flying back from Sydney, you arrive in Los Angeles two hours before you left Sydney!)  The program needs to figure the day as well.  Long distance rates may be very low on Sunday but you can make a Sunday business call across the Date Line to Monday in the Pacific Rim.  The program should allow for that possibility.  Conversely, if you dial across the Date Line on a Friday to a Saturday, or on a Saturday to a Sunday, you run an increasing risk of a business being closed.  The program should also be adaptable to personal calls, so we will make computing business hours a user specified option.
  52.  
  53. AUSTIME.REXX
  54. This program allows the user to choose System time (by pressing [Enter] at the prompt), or to input an hour in HH format.  I chose to use Military or 24 hour time to eliminate AM and PM.  After you input a time here, the program displays a line telling you what time you chose here and what time/day that corresponds to in Sydney.  If you enter your own hour, HH, then the program will display "today" for here and either "today" or "tomorrow" for Sydney, depending on the input hour.  If you input 0 or 24, the program will display "midnight" here and "same day" for Sydney.  If you choose System time by entering a null string, the program will display hours minutes and seconds, and the actual day here, such as "Wednesday", but other output is the same.
  55.  
  56. The first thing after the obligatory comment is the use of the DATE() function without arguments.  This returns a string in the form:
  57.  
  58. DD MMM YYYY 
  59.  
  60. The default for the DATE() function is as if a NORMAL argument had been specified (e.g. it returns a string such as: 25 DEC 1994).  Next the program parses the variable, datenow, into day, month and year with target variables so named.  To compute leap years, leap is set to equal 0 initially.  The remainder (//) operator divides the current year by 4, and returns the remainder.  If the result is zero, then we have a leap year and set leap=1 representing one day at the end of February.  DATE(d) returns the ordinal day of the year, and that is assigned to daynow.  The next IF clause tests to see if Daylight Savings Time is in effect.  MDT starts on day 92 (93 in leap years) or April 31st.  Conversely, October 30th, or day 303 (304 in a leap year) is the day for returning to Standard Time.  The IF statement says, "IF we are in daylight time, THEN the number of hours to add=16; ELSE add=18."  ELSE takes care of the rest of the year, on Standard Time.
  61.  
  62. After a prompt for user input, the program PULLs timenow, (assigns the user input to the token, timenow).  The two parse statements get rid of any punctuation in the input such as "hours:minutes" or some such pattern.  Parsing on a pattern throws out the pattern string, and only keeps the first part of the string up to the pattern.  You may also want to add code to warn the user if input is not in the range 0 to 24.
  63.  
  64. If nothing is entered, the program gets the System time with a TIME() function, similar to DATE() except that its NORMAL option is a string with format
  65.  
  66. HH:MM:SS
  67.  
  68. The token, daynow, is set to DATE(w) or the day of the week, spelled out.  
  69. The ELSE clause covers the case where the user has supplied an arbitrary time of day to convert.  In that case daynow is set to "today".  The next clause tests for midnight, and assigns "midnight" to daynow.  Next, we need to format the resulting number.  FORMAT() is a built-in function of SAA (IBM standard) REXX, but NOT of ARexx.  I chose to make an internal function by that name, because I originally wrote the program in OS/2 REXX where FORMAT() is available.  It was a simple matter to write an internal function that takes the same arguments, even if it doesn't actually do what the REXX FORMAT() does.  I mention this to point out that the "same" language is not always immediately portable between platforms.  Let's hope Bill Hawes makes the next version of ARexx follow ANSI and SAA REXX standards in the interests of portability, communicating with other platforms in networks and so on.  ARexx is not exactly a superset of REXX, because is missing some of the SAA REXX standard functions.  Input/output must of course be platform dependent, but as much standardization as possible should be a priority.
  70.  
  71. The internal FORMAT() function takes three arguments separated by commas, just like the standard REXX function, but it does not do everything the original does.  Note the way the function is defined to be a PROCEDURE so that variables will be completely separate and protected.  Also note the way the argument list is passed in order.  The first argument (the result of the first expression up to the first comma) is placed into "num", followed by a 2 placed into "before" and a 2 placed into "after".  The RIGHT function pads the hour to the left with 0's, so that "1" will come out "01" and so on.  Double digit numbers will not be affected.  Next a colon (:) is placed to the right of the number and two 0's added using the function, COPIES(string,number), where (string) is copied (number) times.  For our purposes here, we do not need anything so fancy, but it illustrates how to make this function mimic the template of the original FORMAT() which has arguments for the number of digits "before" and "after" the decimal point (which we have replaced with a colon).  Finally FORMAT() returns the number "2" formatted as "02:00" for 2 AM, to complete the IF THEN ELSE block.
  72.  
  73. The next line,
  74.  
  75. PARSE VAR timenow hours +2 minutes +3 seconds
  76.  
  77. uses relative positions instead of patterns to divide (parse) the string represented by timenow and does not remove the colons (:).  It counts the positions in the string HH:MM:SS as follows: first 2 positions; next three; the rest of the string.  Absolute positions 3 and 6 could also have been used in our template instead of relative positions +2 and +3.  Just divide the string into hours="HH" minutes=":MM" and seconds=":SS".  These will be concatenated to the answer at the end.
  78.  
  79. Another IF THEN ELSE construction tests for whether it is tomorrow or today in Sydney.  Hours+add (the time in hours here, plus either 16 or 18) is tested to see if it is more than 24 (midnight).  If it is not, then daythere="today"; and if it is, then daythere="tomorrow".  I also added a specific test for midnight in each block to make daythere="same day".  The remainder operator (//) is invoked to restrict the range of the result of hours+add.  A clock's hour must be between 1 and 24.  A clock is an analog of what is called modular arithmetic.  When we get to 24 we begin counting at 1 and not 25.  We say 1 is congruent to 25 mod 24.  1 is the remainder after division by an integer, 24.  AM/PM clocks count time modulo 12.
  80.  
  81. Before output, the result need to be formatted by the format procedure only if the user has input a number.  Testing minutes for null is sufficient to determine this.  When parse could not assign a value to the target, minutes, it was assigned the null string.  The output creates an expression with all the relevant strings concatenated with quoted literal strings (string tokens).  The result is displayed with SAY.
  82.  
  83. AUSTIME2.REXX
  84. The second program is a variation on the first.  It demonstrates how to add help to mimic the behavior of AmigaDOS commands.  If you enter at the prompt
  85.  
  86. RX AUSTIME2 ?
  87.  
  88. then the lines of help are displayed just like in AmigaDOS.  Parse Arg finds the question mark if it is an argument.  This technique is handy for displaying operating instructions or a template.
  89.  
  90. Users are asked if they want a list restricted to Sydney business hours.  A non-Yes simply displays a table of all discount calling times for today.  In both cases MCI Call Pacific discounts times are hard coded.  It's cheap to call only after ten at night and before 2 PM the next day, and all 24 hours on Saturday and Sunday.  The tables do not include any of the expensive times.  If I wanted a program to include Call Europe with different discount times, I would make a new program and call it EURTIME2.REXX.  Then I might make a handler program to call either AUSTIME2.REXX or EURTIME2.REXX as external functions depending on user input.  This way my programs remain small and modular, easy to change or debug.
  91.  
  92. Logic to use the actual day of the week for "today" and "tomorrow" occupies the SELECT block.  A variable, weekend, is set according to whether it's a good day, a bad day, or a maybe day over there with respect to calling during business hours.  A DO loop lists all the hours depending upon whether they are discount AND business, or just discount.  Three messages are output according to whether System time is in or near the weekend.  Good business hours are deemed to be 8:00 to 17:00 Monday through Friday.  Saturday displays a caution message with the same hours.  A simple IF test restricts output to business hours only if a boolean token, biz, is set to 1 after the user answers Y or yes.  Note the way to use the ABBREV() function to accept all variations of "yes".  It merely looks for the first letter, "Y".  PULL insures the user response is in upper case.  
  93.  
  94. You could adapt this program to fax or download/upload at appropriate hours from an ARexx capable fax or terminal program, or you could adapt my program to keep track of what time it is anywhere in the world. and sent with SendIO()TEXT???$                       or BeginIO().TEXT???:   CreateIORequest() - Create and initialize an IO requestTEXT???!                       structure.?TEXT???;   DeleteIORequest() - Free an IO request structure created?TEXT???,                       by CreateIORequest().TEXT????TEXT???/The device support procedures in amiga.lib are:?TEXT????TEXT???<   BeginIO()         - this procedure is almost identical toTEXT???!                       SendIO(). ?TEXT???;   CreateExtIO()     - Create and initialize an extended IO?TEXT???*                       request structure. TEXT???:   CreateStdIO()     - Create and initialize a standard IOTEXT???)                       request structure.?TEXT???;   DeleteExtIO()     - Free an IO request structure created?TEXT???(                       by CreateExtIO().TEXT???;   DeleteStdIO()     - Free an IO request structure created?TEXT???(                       by CreateStdIO().TEXT????TEXT??AAll of the above procedures (except those that create and initialize IO request structures) require a pointer to an IO request structure.  Programs use this structure to communicate with all exec devices.  IO requests are either "standard" or "extended" structures.  The definitions for both standard and extended IO request structures are in the include file, exec/io.h.  This include file defines two IO request structures:  struct IORequest, a "generic" IO request structure;  and struct IOStdReq, a "standard" IO request structure.  The definitions of thes #==========================================================
  95. #
  96. #  Listing 7.  userdev.make 
  97. #
  98. #  makefile for user.device executable
  99. #
  100. #==========================================================
  101.  
  102. HDR = 
  103. INC = INCLUDE:
  104. SRC = 
  105. OBJ = 
  106. FLAGS = nostartup nostackcheck code=far data=far
  107. DBG = 
  108.  
  109. usrdev:  userent.o userinit.o userdev.o link
  110.    @echo "--- user.device compiled and linked ---"
  111.  
  112. link:
  113.     slink FROM userent.o userinit.o userdev.o\
  114.     TO DEVS:user.device \
  115.     LIB LIB:sc.lib LIB:amiga.lib 
  116.  
  117. userent.o:   /* AUSTIME.REXX Convert to time in Australia NSW */
  118. /* Copyright 1994 by Merrill Callaway            */
  119.  
  120. datenow=DATE()
  121. PARSE VAR datenow day month year
  122. leap=0
  123. IF year//4=0 THEN leap=1
  124. daynow=DATE(d)
  125. IF (daynow>93+leap) & (daynow< 303 + leap) THEN add=16
  126. ELSE add=18
  127. SAY 'Input time of day here. hh [Enter]=time now.'
  128. PULL timenow
  129. PARSE VAR timenow timenow ':'
  130. PARSE VAR timenow timenow '.'
  131.  
  132.  
  133. IF timenow= '' THEN DO
  134.    timenow=time()
  135.    daynow=DATE(w)
  136. END
  137. ELSE DO
  138.    daynow='today'
  139.    IF timenow=0 | timenow=24 THEN daynow='midnight'
  140.    timenow=format(timenow,2,2)
  141. END
  142.  
  143. PARSE VAR timenow hours +2 minutes +3 seconds
  144. IF hours+add<24  THEN DO
  145.    hoursthere=hours+add
  146.    daythere='today.'
  147.    IF timenow='00:00' THEN daythere='same day.'
  148. END
  149. ELSE DO
  150.    hoursthere=(hours+add)//24
  151.    daythere='tomorrow.'
  152.    IF timenow='24:00' THEN daythere='same day.'
  153. END
  154.  
  155. IF minutes = '' THEN hoursthere=FORMAT(hoursthere,2,2)
  156. SAY 'Here: 'timenow daynow'. ==> Australia: 'hoursthere||minutes||seconds daythere
  157. EXIT
  158.  
  159. format: PROCEDURE
  160. PARSE ARG num, before, after
  161. num=RIGHT(num,before,0)
  162. num=num':'COPIES('0',after)
  163. RETURN numtialize to let a device know what you want it to do.  All devices recognize a common set of commands that are #define'd in io.h.  These common commands are:TEXT????PARA???%??????? TEXT???;   CMD_INVALID - Place-holder command for the first command?TEXT???;                 number that is less than a valid command. ?TEXT???:   CMD_RESET   - Reset a device.  Generally used to returnTEXT???0                 a device to an "initial" state.TEXT???6   CMD_READ    - Read data from a device or one of itsTEXT???                 io units.TEXT???5   CMD_WRITE   - Write data to a device or one of its?TEXT???                 io units.TEXT???!   CMD_UPDATE  - Update a device.?TEXT???4   CMD_CLEAR   - Clear a device or one of its units.TEXT???:   CMD_STOP    - Stop a device.  This is generally used toTEXT???;                 turn off actual hardware.  It is also used?TEXT???$                 to "pause" devices.TEXT???;   CMD_START   - Start a device.  This is generally used to?TEXT???:                 turn on actual hardware.  It is also usedTEXT???.                 to restart "paused" commands.TEXT???4   CMD_FLUSH   - Flush any buffered data or commandsTEXT???-                 previously sent to a device.?TEXT???5   CMD_NONSTD  - Place-holder for the first available?TEXT???*                 device-specific command. TEXT????TEXT??sEven though all devices recognize the above commands, some devices may not do anything when they receive one of them, and some devices may implement these commands differently than other devices.  Devices may also implement commands in addition to those listed above.  The "Devices" volume of the RKM documents the commands implemented by all the standard Amiga devices. ?PARA?????????? TEXT????TEXT??FIn addition to initializing the io_Command field, you generally need to initialize other fields in the IO request structure to communicate with a device.  The fields you initialize depend on the command you